Set 1 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Audio 1

Q1: What is the difference between Feign and RestTemplate in Spring?

Feign is a declarative web service client that integrates with Spring Cloud, allowing you to create HTTP clients with annotations. RestTemplate, on the other hand, is a more traditional Spring-based approach for making HTTP requests to remote services. Feign is typically easier to use and less boilerplate-heavy than RestTemplate.

@FeignClient(name = "user-service") 
public interface UserClient { 
    @RequestMapping("/users/{id}") 
    User getUser(@PathVariable("id") String id); 
}
Q2: How do you use RestTemplate to call a REST API in Java?

In RestTemplate, you can use the getForObject() or postForObject() methods to call a REST API. You need to create a RestTemplate bean, which will be used for communication with the API.

RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/api/users/1";
User user = restTemplate.getForObject(url, User.class);
Q3: How does WebClient differ from RestTemplate in Spring?

WebClient is the non-blocking, reactive alternative to RestTemplate. It supports asynchronous communication and allows for a more efficient handling of requests, especially in reactive applications. RestTemplate is blocking and synchronous, while WebClient provides better scalability and performance in modern applications.

WebClient webClient = WebClient.create();
Mono userMono = webClient.get()
        .uri("http://example.com/api/users/1")
        .retrieve()
        .bodyToMono(User.class);
Q4: What are the advantages of using Feign in microservice architectures?

Feign simplifies service-to-service communication by providing declarative HTTP client interfaces. It reduces boilerplate code, integrates well with Spring Cloud, and automatically handles error responses, retries, and load balancing when used with Spring Cloud Netflix (Eureka, Ribbon). It also supports configuration via annotations, making it easier to maintain and modify.

Q5: How do you handle error responses with RestTemplate in Java?

In RestTemplate, you can handle error responses by using an HttpErrorHandler or catching exceptions such as HttpClientErrorException and HttpServerErrorException to capture and process error details.

try {
    User user = restTemplate.getForObject(url, User.class);
} catch (HttpClientErrorException e) {
    // Handle client-side errors
} catch (HttpServerErrorException e) {
    // Handle server-side errors
}
Q6: How do you create a Feign client in Spring Boot?

To create a Feign client in Spring Boot, you need to annotate your interface with @FeignClient and provide the service name. You can then define the endpoints in the interface using Spring MVC annotations such as @RequestMapping.

@FeignClient(name = "user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q7: How do you perform asynchronous HTTP requests with WebClient in Spring?

WebClient supports asynchronous HTTP requests using Mono and Flux types. You can perform an asynchronous request by invoking the retrieve() method and handling the response asynchronously using subscribe().

webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user.getName()));
Q8: How do you configure timeouts for WebClient in Spring?

You can configure timeouts for WebClient by using a custom ClientHttpConnector that applies connection and response timeouts. This is typically done with ReactorNettyHttpClient in Spring WebFlux.

ConnectionProvider provider = ConnectionProvider.builder("custom")
    .maxIdleTime(Duration.ofSeconds(30))
    .maxLifeTime(Duration.ofMinutes(5))
    .build();

HttpClient httpClient = HttpClient.create(provider)
    .responseTimeout(Duration.ofSeconds(10));

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(httpClient))
    .build();
Q9: What is the purpose of the @RequestMapping annotation in Feign?

The @RequestMapping annotation in Feign is used to map a method in the Feign client interface to a REST endpoint. It specifies the HTTP method (GET, POST, PUT, DELETE) and the URL path for the request.

@FeignClient(name = "user-service")
public interface UserClient {
    @RequestMapping(method = RequestMethod.GET, value = "/users/{id}")
    User getUser(@PathVariable("id") String id);
}

Set 2 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q10: How do you configure a custom error handler in RestTemplate?

You can configure a custom error handler by implementing the ResponseErrorHandler interface and setting it on a RestTemplate instance using setErrorHandler().

public class CustomErrorHandler implements ResponseErrorHandler {
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR || 
                response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // Handle error based on response status
    }
}

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomErrorHandler());
Q11: What is the benefit of using WebClient for service-to-service communication?

WebClient provides several benefits, such as support for non-blocking, reactive programming. It can handle large-scale, concurrent requests with better performance, as it allows for asynchronous communication and is ideal for reactive applications.

Q12: How can you use Feign with Spring Cloud for service discovery?

You can use Feign with Spring Cloud by combining it with a service discovery tool like Eureka. Feign will automatically resolve service names through the service registry to communicate with other services in the system.

@EnableFeignClients
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@FeignClient(name = "user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q13: What is the difference between Mono and Flux in WebClient?

Mono is a reactive type that represents a single or empty asynchronous value. Flux is used for representing a sequence of asynchronous values. WebClient uses these types to handle single or multiple responses from a service.

Mono userMono = webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class);

Flux usersFlux = webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .bodyToFlux(User.class);
Q14: How do you handle retries in Feign clients?

You can enable automatic retries in Feign by using Spring Cloud Netflix's Retryer class. You can configure the retry policy using the @FeignClient annotation.

@FeignClient(name = "user-service", configuration = RetryConfig.class)
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Configuration
public class RetryConfig {
    @Bean
    public Retryer retryer() {
        return new Retryer.Default(100, 1000, 3);  // Initial, max interval, max attempts
    }
}
Q15: How can you integrate WebClient with a custom authentication header?

You can add custom authentication headers to WebClient requests by using the header() method to set authentication tokens or other headers.

webClient.get()
    .uri("http://example.com/api/users/1")
    .header("Authorization", "Bearer token_value")
    .retrieve()
    .bodyToMono(User.class);
Q16: What is the role of WebClient.Builder in service-to-service communication?

WebClient.Builder allows you to customize WebClient instances. You can set base URLs, add filters, or configure default headers and codecs before creating the WebClient instance.

WebClient webClient = WebClient.builder()
    .baseUrl("http://example.com")
    .defaultHeader("Authorization", "Bearer token_value")
    .build();
Q17: How does RestTemplate handle JSON response mapping?

RestTemplate uses HttpMessageConverter to map JSON responses to Java objects. By default, it uses MappingJackson2HttpMessageConverter for JSON, which automatically deserializes JSON responses into Java objects.

RestTemplate restTemplate = new RestTemplate();
User user = restTemplate.getForObject("http://example.com/api/users/1", User.class);
Q18: Can you perform file uploads with Feign? How?

Yes, you can perform file uploads with Feign by using the MultipartFile class in the Feign client interface. You need to use the @RequestPart annotation to send the file as part of the multipart request.

@FeignClient(name = "file-service")
public interface FileClient {
    @RequestMapping(method = RequestMethod.POST, value = "/upload")
    String uploadFile(@RequestPart("file") MultipartFile file);
}
Q19: How do you enable synchronous calls with WebClient?

To make synchronous calls with WebClient, you can use the block() method, which blocks the calling thread until the response is received.

Mono userMono = webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class);

User user = userMono.block(); // Blocks the thread until the response is received

 

Set 3 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q20: How can you perform asynchronous communication using RestTemplate?

RestTemplate does not support asynchronous communication out of the box. However, you can wrap the RestTemplate calls in a Future or CompletableFuture to achieve asynchronous behavior.

ExecutorService executor = Executors.newFixedThreadPool(1);
Callable task = () -> restTemplate.getForObject("http://example.com/api/users/1", User.class);
Future future = executor.submit(task);
User user = future.get();
Q21: How can you perform asynchronous communication using WebClient?

WebClient supports asynchronous communication out of the box by returning Mono or Flux, which represent asynchronous results.

Mono userMono = webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class);

// To trigger the call asynchronously
userMono.subscribe(user -> System.out.println(user.getName()));
Q22: How do you handle timeouts in WebClient?

You can configure timeouts in WebClient using the baseUrl() and timeout() methods, or by customizing the underlying HttpClient configuration.

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create().responseTimeout(Duration.ofSeconds(5))))
    .baseUrl("http://example.com")
    .build();
Q23: How do you handle retries with WebClient?

WebClient does not have built-in retry functionality, but you can use Retry from the reactor-extra library to add retries.

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create()
            .retry(3))) // Retry 3 times
    .baseUrl("http://example.com")
    .build();
Q24: What is the difference between synchronous and asynchronous communication in WebClient?

Synchronous communication blocks the calling thread until the response is received, while asynchronous communication returns control to the calling thread immediately and processes the response when it is available.

// Synchronous
User user = webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class)
    .block();

// Asynchronous
webClient.get()
    .uri("http://example.com/api/users/1")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user.getName()));
Q25: How can you make service calls with multiple paths using WebClient?

You can use placeholders in the URI and bind them using uri() method with uriVariables.

webClient.get()
    .uri("http://example.com/api/users/{id}/details", 1)
    .retrieve()
    .bodyToMono(User.class);
Q26: How do you use Feign with authentication headers?

In Feign, you can use a request interceptor to add authentication headers to your requests.

@Configuration
public class FeignConfig {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> requestTemplate.header("Authorization", "Bearer token_value");
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q27: How do you configure a timeout in Feign?

You can configure timeouts in Feign by setting connectTimeout and readTimeout in the Feign.Builder.

@Bean
public Request.Options options() {
    return new Request.Options(5000, TimeUnit.MILLISECONDS, 5000, TimeUnit.MILLISECONDS, true);
}
Q28: How do you log requests and responses in Feign?

Feign allows you to log requests and responses using a Logger implementation.

@Bean
Logger.Level feignLoggerLevel() {
    return Logger.Level.FULL;
}
Q29: What is the default logging level in Feign?

The default logging level in Feign is NONE, meaning it does not log requests or responses unless explicitly configured.

 

Set 4 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q30: How do you handle retries in Feign?

You can enable retries in Feign by configuring a retryer in the Feign client. The default retryer retries up to 5 times with an increasing delay.

@FeignClient(name = "user-service", retryer = Retryer.NEVER_RETRY)
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q31: How do you configure Feign for custom error handling?

You can configure a custom error decoder to handle errors in Feign.

@Bean
public ErrorDecoder errorDecoder() {
    return new CustomErrorDecoder();
}

public class CustomErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 404) {
            return new CustomNotFoundException("Not Found");
        }
        return new Exception("Generic error");
    }
}
Q32: How can you use WebClient to handle a POST request?

WebClient can be used for sending a POST request by specifying the request body and calling the post() method.

webClient.post()
    .uri("http://example.com/api/users")
    .bodyValue(new User("John", "Doe"))
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(response -> System.out.println(response.getName()));
Q33: How do you handle request headers in WebClient?

In WebClient, you can add request headers by using the header() method.

webClient.get()
    .uri("http://example.com/api/users")
    .header("Authorization", "Bearer token")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user.getName()));
Q34: What is the role of WebClient’s retrieve() method?

The retrieve() method in WebClient is used to start the actual HTTP request. It returns a ResponseSpec, which is used to specify how to handle the response (e.g., mapping it to a Java object).

webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user.getName()));
Q35: How can you configure Feign with Spring Cloud to work with Eureka?

You can use Spring Cloud Feign with Eureka by enabling Feign clients in your Spring Boot application and specifying the service name to interact with.

@EnableFeignClients
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

    }
}

@FeignClient("user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q36: How do you log request/response headers in WebClient?

In WebClient, you can log request/response headers by using a custom ExchangeFilterFunction that logs the headers.

ExchangeFilterFunction logRequest = ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
    System.out.println("Request: " + clientRequest.headers());
    return Mono.just(clientRequest);
});

ExchangeFilterFunction logResponse = ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
    System.out.println("Response: " + clientResponse.headers());
    return Mono.just(clientResponse);
});

WebClient webClient = WebClient.builder()
    .filter(logRequest)
    .filter(logResponse)
    .baseUrl("http://example.com")
    .build();
Q37: How do you handle content type in WebClient?

In WebClient, you can specify the content type of the request by using the contentType() method.

webClient.post()
    .uri("http://example.com/api/users")
    .contentType(MediaType.APPLICATION_JSON)
    .bodyValue(new User("John", "Doe"))
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(response -> System.out.println(response.getName()));
Q38: How can you handle different response types with Feign?

You can handle different response types in Feign by specifying the return type and using Spring’s ResponseEntity for more control over the response.

@FeignClient("user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    ResponseEntity getUser(@PathVariable("id") String id);
}
Q39: How do you use Feign for service discovery with Ribbon?

In Spring Cloud, Feign and Ribbon work together for client-side load balancing. Feign will interact with Eureka for service discovery, and Ribbon will handle the load balancing.

@EnableFeignClients
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@FeignClient(name = "user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

 

Set 5 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q40: How do you make a GET request with RestTemplate?

In RestTemplate, you can make a GET request by using the getForObject() method.

RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/api/users/{id}";
User user = restTemplate.getForObject(url, User.class, "123");
Q41: How do you use RestTemplate to post JSON data to an endpoint?

You can send JSON data in a POST request using RestTemplate by using the postForObject() method and setting the body.

RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/api/users";
User user = new User("John", "Doe");
User createdUser = restTemplate.postForObject(url, user, User.class);
Q42: How do you configure WebClient with a base URL?

You can configure WebClient with a base URL using the baseUrl() method while building the WebClient instance.

WebClient webClient = WebClient.builder()
    .baseUrl("http://example.com")
    .build();
Q43: How do you handle timeouts with RestTemplate?

You can configure timeouts for RestTemplate by setting a custom ClientHttpRequestFactory with a timeout configuration.

int timeout = 5000; // 5 seconds
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
RequestConfig requestConfig = RequestConfig.custom()
    .setConnectTimeout(timeout)
    .setSocketTimeout(timeout)
    .build();
HttpClient httpClient = HttpClients.custom()
    .setDefaultRequestConfig(requestConfig)
    .build();
factory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
Q44: How can you set a custom error decoder in Feign?

Feign allows you to set a custom error decoder to handle specific error conditions. You can create your custom decoder and configure it using the errorDecoder() bean.

@Bean
public ErrorDecoder errorDecoder() {
    return new CustomErrorDecoder();
}

public class CustomErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 404) {
            return new NotFoundException("Resource not found");
        }
        return new Exception("Generic error");
    }
}
Q45: What is the purpose of WebClient's exchange() method?

The exchange() method in WebClient allows for more control over the response, including access to the full ClientResponse.

webClient.get()
    .uri("http://example.com/api/users")
    .exchange()
    .flatMap(response -> response.bodyToMono(User.class))
    .subscribe(user -> System.out.println(user.getName()));
Q46: How do you handle exceptions with RestTemplate?

RestTemplate can throw different exceptions like HttpClientErrorException or HttpServerErrorException. You can handle these exceptions using a try-catch block.

try {
    User user = restTemplate.getForObject(url, User.class);
} catch (HttpClientErrorException e) {
    // handle client error
} catch (HttpServerErrorException e) {
    // handle server error
} catch (Exception e) {
    // handle generic error
}
Q47: What is the main difference between Feign and RestTemplate?

The main difference is that Feign is declarative and allows you to define client interfaces for HTTP calls, while RestTemplate is a more imperative way of making HTTP requests programmatically.

@FeignClient("user-service")
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q48: How do you configure the WebClient timeout settings?

You can configure timeout settings in WebClient by using a HttpClient with custom timeout configurations.

Duration timeout = Duration.ofSeconds(5);
WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create()
            .responseTimeout(timeout)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
    ))
    .baseUrl("http://example.com")
    .build();
Q49: How do you call a REST API asynchronously with WebClient?

You can make asynchronous calls with WebClient by using the subscribe() method or returning a Mono or Flux.

webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user.getName()));

 

 

Set 6 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q50: How do you create a Feign client interface in Spring?

To create a Feign client interface, you annotate the interface with @FeignClient and define the methods for API calls.

@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q51: How do you make a PUT request using WebClient?

You can make a PUT request using WebClient by calling put() and passing the body of the request.

WebClient webClient = WebClient.create();
webClient.put()
    .uri("http://example.com/api/users/{id}", 123)
    .bodyValue(updatedUser)
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q52: How do you configure Feign to use a custom logger?

Feign allows you to set a custom logger by specifying a Logger.Level in the @FeignClient annotation or configuration.

@FeignClient(name = "user-service", configuration = CustomFeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Configuration
public class CustomFeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
Q53: How do you handle HTTP errors in WebClient?

In WebClient, you can handle HTTP errors by using the onStatus() method to check for specific response statuses.

webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new CustomClientException("Client error")))
    .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new CustomServerException("Server error")))
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q54: How do you perform basic authentication using RestTemplate?

To perform basic authentication with RestTemplate, you need to set the Authorization header using HttpHeaders.

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("username", "password");
HttpEntity entity = new HttpEntity<>(headers);
RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/api/users";
ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, User.class);
Q55: How can you log requests and responses in Feign?

You can log requests and responses in Feign by configuring the Logger class and setting the Logger.Level.

Logger.Level feignLoggerLevel = Logger.Level.FULL;
@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @RequestMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
Q56: How do you pass query parameters in WebClient?

You can pass query parameters in WebClient by using the uri() method with UriComponentsBuilder or by directly specifying the parameters in the URI string.

WebClient webClient = WebClient.create();
webClient.get()
    .uri("http://example.com/api/users?age={age}&city={city}", 30, "New York")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q57: How do you send a JSON payload with a PUT request using RestTemplate?

You can send a JSON payload with a PUT request by creating an HttpEntity with the body and sending it using exchange().

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(updatedUser, headers);
RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/api/users/{id}";
restTemplate.exchange(url, HttpMethod.PUT, entity, User.class, "123");
Q58: What is the advantage of using Feign over RestTemplate?

Feign provides a declarative way to make HTTP requests, which is more concise and easier to maintain compared to RestTemplate's imperative approach.

@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q59: How do you perform a synchronous REST call with WebClient?

WebClient calls are asynchronous by default, but you can block the thread to perform a synchronous call by using block().

User user = webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .block();
Q60: How do you implement retry logic with WebClient?

To implement retry logic with WebClient, you can use retryWhen() and specify the retry conditions.

webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(1)))
    .subscribe(user -> System.out.println(user));

 

Set 7 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q61: How do you configure RestTemplate to handle timeouts?

You can configure timeouts for RestTemplate using HttpClient and setting the connection and read timeouts.

RequestConfig requestConfig = RequestConfig.custom()
    .setConnectTimeout(5000) // 5 seconds
    .setSocketTimeout(5000) // 5 seconds
    .build();

CloseableHttpClient httpClient = HttpClients.custom()
    .setDefaultRequestConfig(requestConfig)
    .build();

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(factory);
Q62: How do you send a POST request with JSON payload using Feign?

To send a POST request with a JSON payload using Feign, you annotate the method with @PostMapping and use RequestBody for the data.

@FeignClient("user-service")
public interface UserClient {
    @PostMapping("/users")
    User createUser(@RequestBody User user);
}
Q63: How do you enable logging for RestTemplate requests?

You can enable logging for RestTemplate by using a RequestLoggingInterceptor and adding it to the RestTemplate.

RequestLoggingInterceptor loggingInterceptor = new RequestLoggingInterceptor();
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(loggingInterceptor);
Q64: How do you handle responses with different content types in WebClient?

WebClient allows you to handle different content types by using the accept() method to specify the expected content type for the response.

webClient.get()
    .uri("http://example.com/api/users")
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q65: How do you use a custom error decoder with Feign?

To use a custom error decoder with Feign, you create a class that implements ErrorDecoder and provide it in the Feign configuration.

public class CustomErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        if (response.status() == 404) {
            return new NotFoundException("Resource not found");
        }
        return new Exception("Generic error");
    }
}

@FeignClient(name = "user-service", configuration = CustomFeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Configuration
public class CustomFeignConfig {
    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}
Q66: How do you use RestTemplate with OAuth2 authentication?

To use RestTemplate with OAuth2 authentication, you need to set the Authorization header with the access token.

HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + accessToken);
HttpEntity entity = new HttpEntity<>(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response = restTemplate.exchange("http://example.com/api/resource", HttpMethod.GET, entity, String.class);
Q67: How do you handle retries in Feign?

Feign supports retry functionality with a Retryer bean that can be configured to control the retry behavior.

@Bean
public Retryer feignRetryer() {
    return new Retryer.Default(100, 1000, 3);
}

@FeignClient(name = "user-service", configuration = RetryConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Configuration
public class RetryConfig {
    @Bean
    public Retryer retryer() {
        return new Retryer.Default(100, 1000, 3); // retry 3 times with exponential backoff
    }
}
Q68: How do you handle exceptions globally with RestTemplate?

To handle exceptions globally with RestTemplate, you can define a ResponseErrorHandler and set it on your RestTemplate instance.

public class CustomErrorHandler implements ResponseErrorHandler {
    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR 
                || response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR;
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // handle the error
    }
}

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new CustomErrorHandler());
Q69: How do you authenticate with API keys in WebClient?

You can authenticate with API keys in WebClient by adding the API key to the Authorization or custom header.

webClient.get()
    .uri("http://example.com/api/users")
    .header("Api-Key", "your-api-key")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q70: How do you log requests and responses in WebClient?

You can log requests and responses in WebClient by using filter() to capture the details of the request and response.

WebClient webClient = WebClient.builder()
    .filter((request, next) -> {
        System.out.println("Request: " + request);
        return next.exchange(request).doOnTerminate(() -> System.out.println("Response: " + request));
    })
    .baseUrl("http://example.com")
    .build();

 

Set 8 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q71: How do you configure a WebClient instance to handle a custom error response?

You can configure a WebClient instance to handle custom error responses by using the onStatus() method to check for the status and then handle the error.

WebClient webClient = WebClient.create("http://example.com");
webClient.get()
    .uri("/users")
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new CustomClientException("Client Error")))
    .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new CustomServerException("Server Error")))
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q72: How do you perform a GET request with RestTemplate and handle response as a list of objects?

You can use RestTemplate to perform a GET request and handle the response as a list of objects using ParameterizedTypeReference.

RestTemplate restTemplate = new RestTemplate();
ResponseEntity> response = restTemplate.exchange(
    "http://example.com/api/users",
    HttpMethod.GET,
    null,
    new ParameterizedTypeReference>() {}
);
List users = response.getBody();
Q73: How do you handle multipart file uploads with RestTemplate?

You can handle multipart file uploads with RestTemplate by creating a MultipartBodyBuilder and sending the request as a multipart/form-data request.

MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("file", new FileSystemResource("path/to/file"));
builder.part("metadata", "Some metadata");

RestTemplate restTemplate = new RestTemplate();
HttpEntity> entity = new HttpEntity<>(builder.build());
ResponseEntity> entity = new HttpEntity<>(builder.build());
ResponseEntity> entity = new HttpEntity<>(builder.build());
ResponseEntity> entity = new HttpEntity<>(builder.build());
ResponseEntity> entity = new HttpEntity<>(builder.build());
ResponseEntity response = restTemplate.exchange(
    "http://example.com/upload",
    HttpMethod.POST,
    entity,
    String.class
);
Q74: How do you configure Feign to use a custom encoder for the request body?

To configure Feign to use a custom encoder, you can provide a Encoder bean in the Feign configuration.

@Configuration
public class FeignConfig {
    @Bean
    public Encoder feignEncoder() {
        return new JacksonEncoder();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @PostMapping("/users")
    User createUser(@RequestBody User user);
}
Q75: How do you make a GET request with WebClient and extract a custom header value from the response?

You can extract custom header values from the response in WebClient by using the headers() method to access the response headers.

webClient.get()
    .uri("http://example.com/api/users")
    .retrieve()
    .toEntity(User.class)
    .doOnSuccess(response -> {
        String customHeader = response.getHeaders().getFirst("X-Custom-Header");
        System.out.println("Custom Header: " + customHeader);
    })
    .subscribe(user -> System.out.println(user));
Q76: How do you send a PUT request using Feign?

To send a PUT request using Feign, you use the @PutMapping annotation on the method, passing the request body as a parameter.

@FeignClient("user-service")
public interface UserClient {
    @PutMapping("/users/{id}")
    User updateUser(@PathVariable("id") String id, @RequestBody User user);
}
Q77: How do you set up a WebClient instance to follow redirects?

You can configure WebClient to follow redirects by setting the followRedirects() method in the WebClient builder.

WebClient webClient = WebClient.builder()
    .baseUrl("http://example.com")
    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .filter((request, next) -> next.exchange(request))
    .build();
Q78: How do you handle API rate limiting in WebClient?

To handle API rate limiting in WebClient, you can use retryWhen() to add retries with delays or use a custom filter to intercept rate-limiting responses.

webClient.get()
    .uri("http://example.com/api/endpoint")
    .retrieve()
    .onStatus(HttpStatus.TOO_MANY_REQUESTS::equals, response -> Mono.error(new RateLimitExceededException("Rate limit exceeded")))
    .bodyToMono(String.class)
    .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(2)))
    .subscribe(response -> System.out.println(response));
Q79: How do you use a custom decoder in Feign for response bodies?

To use a custom decoder in Feign, you can create a Decoder bean and provide it in the Feign configuration.

@Configuration
public class FeignConfig {
    @Bean
    public Decoder feignDecoder() {
        return new CustomDecoder();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q80: How do you configure WebClient to handle retries?

You can configure WebClient to handle retries by using the retryWhen() method in the request pipeline.

webClient.get()
    .uri("http://example.com/api/resource")
    .retrieve()
    .bodyToMono(String.class)
    .retryWhen(Retry.backoff(3, Duration.ofSeconds(2)))
    .subscribe(response -> System.out.println(response));

 

Set 9 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q81: How do you configure a custom retry mechanism for Feign client?

You can configure a custom retry mechanism for Feign by defining a Retryer bean in the Feign configuration.

@Configuration
public class FeignConfig {
    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(100, TimeUnit.MILLISECONDS.toMillis(1), 3);
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q82: How do you perform a POST request with RestTemplate and handle the response body?

You can perform a POST request using RestTemplate and handle the response body by passing the entity to the exchange() method.

RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(new User("John", "Doe"), headers);

ResponseEntity response = restTemplate.exchange(
    "http://example.com/api/users",
    HttpMethod.POST,
    entity,
    User.class
);
User createdUser = response.getBody();
Q83: How do you set the timeout values for WebClient?

You can set the timeout values for WebClient using the baseUrl method and applying a custom exchangeStrategies().

WebClient webClient = WebClient.builder()
    .baseUrl("http://example.com")
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create().responseTimeout(Duration.ofSeconds(10))
    ))
    .build();
Q84: How can you handle invalid responses (4xx, 5xx) in WebClient?

You can handle invalid responses by using the onStatus() method to inspect the HTTP status code and perform custom error handling.

WebClient webClient = WebClient.create("http://example.com");
webClient.get()
    .uri("/api/users")
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, response -> Mono.error(new CustomClientException("Client Error")))
    .onStatus(HttpStatus::is5xxServerError, response -> Mono.error(new CustomServerException("Server Error")))
    .bodyToMono(User.class)
    .subscribe(user -> System.out.println(user));
Q85: How do you authenticate using OAuth2 with WebClient?

You can authenticate using OAuth2 by setting the OAuth2AuthorizedClientManager in WebClient.

OAuth2AuthorizedClientManager authorizedClientManager = 
    new OAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
WebClient webClient = WebClient.builder()
    .baseUrl("http://example.com")
    .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
    .build();
Q86: How do you perform a PUT request with WebClient?

You can perform a PUT request with WebClient by using the put() method and passing the request body.

WebClient webClient = WebClient.create("http://example.com");
webClient.put()
    .uri("/api/users/{id}", 1)
    .bodyValue(new User("Jane", "Doe"))
    .retrieve()
    .bodyToMono(Void.class)
    .subscribe();
Q87: How do you set up Feign with a custom error decoder?

You can set up Feign with a custom error decoder by creating a bean of type ErrorDecoder in the configuration.

@Configuration
public class FeignConfig {
    @Bean
    public ErrorDecoder errorDecoder() {
        return new CustomErrorDecoder();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q88: How do you handle cookies in a WebClient request?

You can handle cookies in WebClient by accessing them from the CookieHandler or by using a custom filter.

WebClient webClient = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(HttpClient.create().cookieHandler(new CookieManager())))
    .build();
Q89: How do you perform an asynchronous request using RestTemplate?

RestTemplate is blocking by default, but you can perform asynchronous requests using AsyncRestTemplate.

AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
ListenableFuture> future = asyncRestTemplate.exchange(
    "http://example.com/api/users",
    HttpMethod.GET,
    null,
    User.class
);
future.addCallback(result -> System.out.println(result.getBody()), ex -> ex.printStackTrace());
Q90: How do you create a Feign client with basic authentication?

You can create a Feign client with basic authentication by using RequestInterceptor to add an authorization header.

@Configuration
public class FeignConfig {
    @Bean
    public RequestInterceptor requestInterceptor() {
        return requestTemplate -> requestTemplate.header(HttpHeaders.AUTHORIZATION, "Basic " + encodedCredentials);
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

Set 10 - Service-to-Service Communication (Feign, RestTemplate, WebClient)

Q91: How can you define timeouts for Feign clients?

You can define timeouts for Feign clients by configuring okhttp3 with custom timeouts.

@Configuration
public class FeignConfig {
    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .build();
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q92: How do you use WebClient with a custom exchange filter function?

You can add a custom filter to WebClient using the filter() method to modify the request and response.

WebClient webClient = WebClient.builder()
    .filter((request, next) -> {
        System.out.println("Request URI: " + request.uri());
        return next.exchange(request);
    })
    .baseUrl("http://example.com")
    .build();
Q93: How do you create a fallback mechanism in Feign?

You can create a fallback mechanism in Feign by using the fallback attribute in the Feign client declaration.

@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}

@Component
public class UserClientFallback implements UserClient {
    @Override
    public User getUser(String id) {
        return new User("Fallback", "User");
    }
}
Q94: How can you add headers to every WebClient request?

You can add headers to every WebClient request by using the defaultHeader() method.

WebClient webClient = WebClient.builder()
    .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .baseUrl("http://example.com")
    .build();
webClient.get()
    .uri("/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .subscribe();
Q95: How do you implement service discovery with Feign and Spring Cloud?

You can implement service discovery with Feign and Spring Cloud by using @EnableFeignClients and @EnableDiscoveryClient annotations, and setting up an application that integrates with Eureka or Consul.

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q96: How do you handle retries with WebClient?

You can handle retries with WebClient by using the retry operator from Project Reactor.

webClient.get()
    .uri("/api/users")
    .retrieve()
    .bodyToMono(User.class)
    .retry(3)  // Retries 3 times before failing
    .subscribe(user -> System.out.println(user));
Q97: How do you log request and response details in WebClient?

You can log request and response details in WebClient by using the exchangeStrategies() method or by adding a custom logging filter.

WebClient webClient = WebClient.builder()
    .filter((request, next) -> {
        System.out.println("Request URI: " + request.uri());
        return next.exchange(request).doOnTerminate(() -> System.out.println("Request completed"));
    })
    .baseUrl("http://example.com")
    .build();
Q98: How can you implement OAuth2 token management in Feign?

You can implement OAuth2 token management in Feign by using RequestInterceptor to attach the token to every request.

@Configuration
public class FeignConfig {
    @Bean
    public RequestInterceptor oauthRequestInterceptor() {
        return requestTemplate -> requestTemplate.header(HttpHeaders.AUTHORIZATION, "Bearer " + getOAuth2Token());
    }
}

@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
    @GetMapping("/users/{id}")
    User getUser(@PathVariable("id") String id);
}
Q99: How do you validate input data before making a REST request using Feign?

You can validate input data by using custom logic or annotations before making a request with Feign.

@FeignClient(name = "user-service")
public interface UserClient {
    @PostMapping("/users")
    void createUser(@Valid @RequestBody User user);
}
Q100: How do you configure a timeout for RestTemplate?

You can configure a timeout for RestTemplate by using a SimpleClientHttpRequestFactory with custom timeouts.

int timeout = 5000;
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(timeout);
factory.setReadTimeout(timeout);
RestTemplate restTemplate = new RestTemplate(factory);